package client

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"gin-epg/internal/app/common/util"
	"gin-epg/internal/app/dao"
	"gin-epg/internal/app/entity"
	"github.com/go-resty/resty/v2"
	"strings"
	"time"
)

// 节目表网页 https://nine.ifeng.com/phtvperiodlist?from=2025-05-08&to=2025-05-12
var mapIfeng = map[string][]string{
	"phtvChinese": {"凤凰中文", "凤凰卫视中文台"},
	"phtvNews":    {"凤凰资讯", "凤凰卫视资讯台"},
	// 更多键值对...
}

type IfengResponse struct {
	Code int `json:"code"`
	Data map[string]map[string][]struct {
		Time  string `json:"time"`
		Title string `json:"title"`
	} `json:"data"`
}

// HandleIfengCron 处理凤凰网 EPG 数据抓取，支持传入前后天数，并支持 insert / update / delete
func HandleIfengCron(beforeDay, afterDay int) error {
	dao.Logger.Infof("HandleIfengCron start (beforeDay=%d, afterDay=%d)", beforeDay, afterDay)
	source := "ifeng"

	client := resty.New()

	// 构造 from 和 to 日期
	fromDate := time.Now().AddDate(0, 0, -beforeDay).Format("2006-01-02")
	toDate := time.Now().AddDate(0, 0, afterDay).Format("2006-01-02")

	url := fmt.Sprintf("https://nine.ifeng.com/phtvperiodlist?from=%s&to=%s", fromDate, toDate)
	proxyURL, err := util.GetConfigValue("proxy.proxyApiUrlIfeng")
	if err != nil {
		dao.Logger.Errorf("Error: %v", err)
	} else {
		dao.Logger.Infof("proxyApiUrlIfeng: %v", proxyURL)
		url = fmt.Sprintf("%s%s", proxyURL, url[len("https://nine.ifeng.com"):])
	}

	resp, err := client.R().
		SetHeaders(map[string]string{
			"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
		}).
		Get(url)

	if err != nil {
		return fmt.Errorf("failed to get data from URL: %v", err)
	}

	body := resp.Body()
	if !strings.Contains(string(body), `"code":0`) {
		return fmt.Errorf("invalid response: %s", body)
	}

	var ifengResp IfengResponse
	if err := json.Unmarshal(body, &ifengResp); err != nil {
		return fmt.Errorf("failed to parse JSON: %v", err)
	}

	if ifengResp.Code != 0 {
		return fmt.Errorf("non-zero code returned: %d", ifengResp.Code)
	}

	db := dao.SqlSession

	for dateStr, channelsMap := range ifengResp.Data {
		for channelKey, programs := range channelsMap {
			mappedChannels, ok := mapIfeng[channelKey]
			if !ok || len(mappedChannels) == 0 {
				continue
			}

			dateParsed, err := time.Parse("2006-01-02", dateStr)
			if err != nil {
				dao.Logger.Warnf("failed to parse date: %v", err)
				continue
			}

			// 获取当前频道和日期下的现有记录
			var existingRecords []entity.EpgProgramCollect
			if err := db.Where("date = ? AND source = ? AND channel IN (?)", dateParsed, source, mappedChannels).Find(&existingRecords).Error; err != nil {
				dao.Logger.Errorf("failed to fetch existing records: %v", err)
				continue
			}

			existingMap := make(map[string]*entity.EpgProgramCollect)
			for i := range existingRecords {
				key := fmt.Sprintf("%s|%s", existingRecords[i].Channel, existingRecords[i].Start)
				existingMap[key] = &existingRecords[i]
			}

			var newPrograms, updatePrograms, deletePrograms []entity.EpgProgramCollect

			// 遍历接口数据，对比并分类处理：新增、更新
			for i := 0; i < len(programs); i++ {
				startTime := programs[i].Time
				endTime := "23:59"
				if i+1 < len(programs) {
					endTime = programs[i+1].Time
				}

				title := programs[i].Title

				for _, mappedChannel := range mappedChannels {
					key := fmt.Sprintf("%s|%s", mappedChannel, startTime)
					epg := entity.EpgProgramCollect{
						Channel:    mappedChannel,
						Date:       entity.NullDate{sql.NullTime{Time: dateParsed, Valid: true}},
						Start:      startTime,
						End:        endTime,
						Title:      title,
						Source:     source,
						CreateTime: entity.NullTime{sql.NullTime{Time: time.Now(), Valid: true}},
					}

					if existingEpg, exists := existingMap[key]; exists {
						if existingEpg.Title != epg.Title || existingEpg.End != epg.End {
							existingEpg.Title = epg.Title
							existingEpg.End = epg.End
							existingEpg.UpdateTime = entity.NullTime{sql.NullTime{Time: time.Now(), Valid: true}}
							updatePrograms = append(updatePrograms, *existingEpg)
						}
						delete(existingMap, key) // 已处理，从待删除列表移除
					} else {
						newPrograms = append(newPrograms, epg)
					}
				}
			}

			// 剩余未被处理的即为应删除的旧记录
			for _, leftover := range existingMap {
				deletePrograms = append(deletePrograms, *leftover)
			}

			// 执行数据库操作
			if len(updatePrograms) > 0 {
				for _, program := range updatePrograms {
					if err := db.Model(&program).Updates(entity.EpgProgramCollect{
						Title:      program.Title,
						End:        program.End,
						UpdateTime: program.UpdateTime,
					}).Error; err != nil {
						dao.Logger.Errorf("update error: %v", err)
					} else {
						dao.Logger.Debugf("updated EPG: %v", program)
					}
				}
			}

			if len(newPrograms) > 0 {
				for _, program := range newPrograms {
					if err := db.Create(&program).Error; err != nil {
						dao.Logger.Errorf("insert error: %v", err)
					} else {
						dao.Logger.Debugf("inserted EPG: %v", program)
					}
				}
			}

			if len(deletePrograms) > 0 {
				for _, program := range deletePrograms {
					if err := db.Delete(&program).Error; err != nil {
						dao.Logger.Errorf("delete error: %v", err)
					} else {
						dao.Logger.Debugf("deleted EPG: %v", program)
					}
				}
			}
		}
	}

	return nil
}
